using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.EntityFrameworkCore;
using StudentVideo.Common.Attributes;
using StudentVideo.Common.Constants;
using StudentVideo.Common.Models;
using StudentVideo.Data;
using StudentVideo.Helper;
using StudentVideo.Shared.Enums;
using StudentVideo.Shared.Models;
using System.Linq.Dynamic.Core;
using System.Security.Claims;

namespace StudentVideo.Filters;

public class CustomAuthorizationFilter(ILogger<CustomAuthorizationFilter> logger, RedisDbHelper redisDb, AppDbContext appDbContext): IAsyncAuthorizationFilter {
   private readonly ILogger<CustomAuthorizationFilter> _logger = logger;
   private readonly RedisDbHelper _redisDb = redisDb;
   private readonly AppDbContext _context = appDbContext;

   public async Task OnAuthorizationAsync(AuthorizationFilterContext context) {
      var httpContext = context.HttpContext;

      // 存在 AllowAnonymousAttribute 时，跳过验证
      var endpoint = httpContext.GetEndpoint();
      var hasAllowAnonymous = endpoint?.Metadata.GetMetadata<AllowAnonymousAttribute>() != null;
      if (hasAllowAnonymous) {
         return;
      }

      // 检查 UserRangeLimitAttribute 是否存在
      var userRangeLimit = endpoint?.Metadata.GetMetadata<UserRangeLimitAttribute>();
      if (userRangeLimit == null) {
         return;
      }

      // 执行默认的身份验证
      var user = httpContext.User;

      if (user?.Identity?.IsAuthenticated == false) {
         _logger.LogWarning(HttpErrorMessage.AUTH_ERROR);
         context.Result = new ObjectResult(new HttpResult<object> {
            StatusCode = 401,
            Message = HttpErrorMessage.AUTH_ERROR,
            Data = null
         }) {
            StatusCode = 200
         };
         return;
      }

      // 从 HttpContext 获取 ClaimsPrincipal
      ClaimsPrincipal principal = httpContext.User;
      var uid = principal.Claims.FirstOrDefault(e => e.Type == UserClaims.Uid)?.Value;
      var userRange = principal.Claims.FirstOrDefault(e => e.Type == UserClaims.UserRange)?.Value;

      if (uid is null || userRange is null) {
         _logger.LogWarning(HttpErrorMessage.ROLE_ERROR);

         context.Result = new ObjectResult(new HttpResult<object> {
            StatusCode = 403,
            Message = HttpErrorMessage.ROLE_ERROR,
            Data = null
         }) {
            StatusCode = 200
         };

         return;
      }

      UserRangeEnum range = Enum.Parse<UserRangeEnum>(userRange!);
      PermissionResult? permissionResult = range switch {
         UserRangeEnum.Internal => await UserPermission(httpContext, uid),
         UserRangeEnum.External => StudentPermission(httpContext, uid),
         _ => new() {
            Code = 403,
            Message = HttpErrorMessage.ROLE_ERROR,
            Success = false
         }
      };

      if (permissionResult.Success == false) {
         context.Result = new ObjectResult(new HttpResult<object> {
            StatusCode = permissionResult.Code,
            Message = permissionResult.Message,
            Data = null
         }) {
            StatusCode = 200
         };
         return;
      }
   }

   private class PermissionResult {
      public int Code { get; set; } = 403;

      public string Message { get; set; } = string.Empty;

      public bool Success { get; set; } = false;
   }

   // TODO 管理员及学生权限功能开发

   /// <summary>
   /// 管理员用户权限
   /// </summary>
   /// <param name="httpContext"></param>
   /// <param name="userId"></param>
   private async Task<PermissionResult> UserPermission(HttpContext httpContext, string userId) {
      CurrentUser current = new() {
         UserId = userId,
         UserRange = UserRangeEnum.Internal,
      };

      // TODO 尝试从 redis 中查询用户信息

      // 尝试从数据库中查询用户信息

      var userinfo = await _context.Users.FirstOrDefaultAsync(e => e.Id == userId);
      if (userinfo == null)
         return new() {
            Code = 401,
            Message = HttpErrorMessage.ROLE_ERROR
         };

      current.UserInfo = userinfo;

      // 查询当前用户的角色信息

      // var roleinfo  = await _context.UserRoleMaps.Select(e => e.UserId)

      return new PermissionResult() { Success = true };
   }

   // TODO 学生(客户端)权限功能开发

   /// <summary>
   /// 学生权限
   /// </summary>
   /// <param name="httpContext"></param>
   /// <param name="studentId"></param>
   /// <returns></returns>
   private PermissionResult StudentPermission(HttpContext httpContext, string studentId) {

      return new PermissionResult();
   }
}
